package com.yanqu.road.server.channelserver.manager.activity.washe.game;

import com.yanqu.road.entity.activity.washe.config.WasheCardConfig;
import com.yanqu.road.entity.activity.washe.config.WasheConfig;
import com.yanqu.road.entity.activity.washe.config.WasheSkillConfig;
import com.yanqu.road.entity.activity.washe.eliminate.WasheBlock;
import com.yanqu.road.entity.activity.washe.eliminate.WasheBlockEffect;
import com.yanqu.road.entity.activity.washe.eliminate.WasheGameData;
import com.yanqu.road.entity.activity.washe.eliminate.WasheMoveParam;
import com.yanqu.road.entity.activity.washe.eliminate.WasheOperateEffect;
import com.yanqu.road.entity.activity.washe.eliminate.WasheOperateResult;
import com.yanqu.road.entity.activity.washe.eliminate.WasheSkill16Color;
import com.yanqu.road.entity.activity.washe.eliminate.WasheSkill18X;
import com.yanqu.road.entity.activity.washe.eliminate.WasheSkill19Color;
import com.yanqu.road.entity.activity.washe.eliminate.WasheUseSkillParam;
import com.yanqu.road.entity.activity.washe.game.WasheUserGameData;
import com.yanqu.road.entity.enums.washe.eWasheBlockEffectType;
import com.yanqu.road.entity.enums.washe.eWasheBlockType;
import com.yanqu.road.entity.enums.washe.eWasheDirectionType;
import com.yanqu.road.entity.enums.washe.eWasheEffectType;
import com.yanqu.road.entity.enums.washe.eWasheOperateType;
import com.yanqu.road.entity.enums.washe.eWasheSkillType;
import com.yanqu.road.entity.enums.washe.eWasheColorType;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Random;
import java.util.Set;
import java.util.stream.Collectors;

public class WasheSkillLogic {

    public static Set<WasheBlock> handleUseSkill(WasheConfig config, Random random, WasheGameData gameData, WasheOperateResult result, WasheUseSkillParam skillParam, WasheUserGameData userGameData, boolean isGuide, int roomRound, int turnPlayer) {
        Set<WasheBlock> skillEliminateSet = new HashSet<>();

        eWasheSkillType skillType = eWasheSkillType.getType(skillParam.getSkillId());
        if (skillType == null) {
            return skillEliminateSet;
        }


        // -------------------------- 卡片技能 ----------------------------
        if (skillType == eWasheSkillType.Card_01) {
            skillEliminateSet = handleSkill_01(config, random, gameData, result, isGuide);
        } else if (skillType == eWasheSkillType.Card_02) {
            skillEliminateSet = handleSkill_02(gameData, result);
        } else if (skillType == eWasheSkillType.Card_03) {
            skillEliminateSet = handleSkill_03(config, random, gameData, result, skillParam);
        } else if (skillType == eWasheSkillType.Card_04) {
            skillEliminateSet = handleSkill_04(config, random, gameData, result);
        } else if (skillType == eWasheSkillType.Card_05) {
            skillEliminateSet = handleSkill_05(random, gameData, result);
        } else if (skillType == eWasheSkillType.Card_06) {
            skillEliminateSet = handleSkill_06(config, random, gameData, result, skillParam);
        } else if (skillType == eWasheSkillType.Card_07) {
            skillEliminateSet = handleSkill_07(config, random, gameData, result);
        } else if (skillType == eWasheSkillType.Card_08) {
            skillEliminateSet = handleSkill_08(gameData, result);
        } else if (skillType == eWasheSkillType.Card_09) {
            skillEliminateSet = handleSkill_09(random, gameData, result, skillParam);
        } else if (skillType == eWasheSkillType.Card_10) {
            skillEliminateSet = handleSkill_10(gameData, result, skillParam);
        } else if (skillType == eWasheSkillType.Card_11) {
            skillEliminateSet = handleSkill_11(gameData, result, skillParam);
        } else if (skillType == eWasheSkillType.Card_12) {
            skillEliminateSet = handleSkill_12(config, random, gameData, result);
        } else if (skillType == eWasheSkillType.Card_13) {
            skillEliminateSet = handleSkill_13(config, random, gameData, result, true);
        } else if (skillType == eWasheSkillType.Card_14) {
            skillEliminateSet = handleSkill_14(config, random, gameData, result, skillParam);
        } else if (skillType == eWasheSkillType.Card_15) {
            skillEliminateSet = handleSkill_15(config, random, gameData, result);
        } else if (skillType == eWasheSkillType.Card_16) {
            skillEliminateSet = handleSkill_16(config, gameData, result, userGameData, skillParam, random, roomRound, turnPlayer);
        } else if (skillType == eWasheSkillType.Card_17) {
            skillEliminateSet = handleSkill_17(config, random, gameData, result);
        } else if (skillType == eWasheSkillType.Card_18) {
            skillEliminateSet = handleSkill_18(config, random, gameData, result);
        } else if (skillType == eWasheSkillType.Card_19) {
            skillEliminateSet = handleSkill_19(random, gameData, result);
        } else if (skillType == eWasheSkillType.Card_20) {
            skillEliminateSet = handleSkill_20(config, random, gameData, result, userGameData, roomRound, turnPlayer);
        } else if (skillType == eWasheSkillType.Card_21) {
            skillEliminateSet = handleSkill_21(config, random, gameData, result);
        } else if (skillType == eWasheSkillType.Card_22) {
            skillEliminateSet = handleSkill_22(config, random, gameData, result, userGameData);
        } else if (skillType == eWasheSkillType.Card_23) {
            skillEliminateSet = handleSkill_23(config, gameData, result, random);
        } else if (skillType == eWasheSkillType.Card_24) {
            skillEliminateSet = handleSkill_24(gameData, skillParam, result);
        }
        // -------------------------- 盘面技能 ----------------------------
        else if (skillType == eWasheSkillType.Skill_1001) {
            skillEliminateSet = handleSkill_1001(random, gameData, result);
        } else if (skillType == eWasheSkillType.Skill_1002) {
            skillEliminateSet = handleSkill_1002(gameData, skillParam, result);
        } else if (skillType == eWasheSkillType.Skill_1003) {
            skillEliminateSet = handleSkill_1003(config, gameData, result, userGameData, skillParam, random, roomRound, turnPlayer);
        } else if (skillType == eWasheSkillType.Skill_1004) {
            skillEliminateSet = handleSkill_1004(config, random, gameData, result);
        } else if (skillType == eWasheSkillType.Skill_1005) {
            skillEliminateSet = handleSkill_1005(config, random, gameData, result);
        } else if (skillType == eWasheSkillType.Skill_1006) {
            skillEliminateSet = handleSkill_1006(config, gameData, result, skillParam);
        } else if (skillType == eWasheSkillType.Skill_1007) {
            skillEliminateSet = handleSkill_1007(config, random, gameData, result, skillParam);
        } else if (skillType == eWasheSkillType.Skill_1008) {
            skillEliminateSet = handleSkill_1008(config, random, gameData, result);
        } else if (skillType == eWasheSkillType.Skill_1009) {
            skillEliminateSet = handleSkill_1009(config, random, gameData, result);
        } else if (skillType == eWasheSkillType.Skill_1010) {
            skillEliminateSet = handleSkill_1010(config, gameData, result, skillParam);
        } else if (skillType == eWasheSkillType.Skill_1011) {
            skillEliminateSet = handleSkill_1011(config, gameData, result, skillParam);
        } else if (skillType == eWasheSkillType.Skill_1012) {
            skillEliminateSet = handleSkill_1012(config, random, gameData, result, skillParam);
        } else if (skillType == eWasheSkillType.Skill_1013) {
            skillEliminateSet = handleSkill_1013(config, gameData, result, skillParam);
        }


        return skillEliminateSet;
    }

    // ================================================================

    private static Set<WasheBlock> handleSkill_01(WasheConfig config, Random random,
                                                  WasheGameData gameData, WasheOperateResult result, boolean isGuide) {

        // 技能参数
        WasheCardConfig cardConfig = config.getCardConfigMap().get(eWasheSkillType.Card_01.getValue());
        long paramCount = cardConfig.getSkillParamList().get(0);

        // 可使用格子
        List<List<WasheBlock>> blockList = gameData.getBlockList();
        List<WasheBlock> all = new ArrayList<>();
        for (List<WasheBlock> list : blockList) {
            for (WasheBlock block : list) {
                if (block.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL
                        || block.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL_BOMB
                        || block.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_SPECIAL
                        || block.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_SPECIAL_BOMB) {
                    all.add(block);
                }
            }
        }

        // 选择格子
        Collections.shuffle(all, random);
        Set<WasheBlock> set = new HashSet<>();
        for (WasheBlock block : all) {
            if (set.size() >= paramCount) {
                break;
            }
            set.add(block);
        }

        // 新手引导替换
        if (isGuide) {
            set = WasheFirstGameLogic.getCardResult1(blockList);
        }

        // 技能效果
        WasheOperateEffect operateEffect = new WasheOperateEffect(eWasheSkillType.Card_01, 1);
        operateEffect.setBlockList(new ArrayList<>(set));
        result.addEffect(operateEffect);
        result.addEffect(new WasheOperateEffect(eWasheSkillType.Card_01, 0)); // 添加技能效果结束

        return set;
    }

    private static Set<WasheBlock> handleSkill_02(WasheGameData gameData, WasheOperateResult result) {
        List<List<WasheBlock>> blockList = gameData.getBlockList();

        // 选择哪列
        int colIndex = blockList.get(0).size() / 2;

        // 消除
        Set<WasheBlock> all = new HashSet<>();
        for (List<WasheBlock> list : gameData.getBlockList()) {
            WasheBlock block = list.get(colIndex);
            if (WasheGameLogic.isBaseFourBigType(block)) {
                all.add(block);
            }
        }

        // 效果
        WasheOperateEffect effect = new WasheOperateEffect(eWasheSkillType.Card_02, 1);
        effect.setBlockList(new ArrayList<>(all));
        result.addEffect(effect);
        result.addEffect(new WasheOperateEffect(eWasheSkillType.Card_02, 0));

        return all;
    }

    private static Set<WasheBlock> handleSkill_03(WasheConfig config, Random random,
                                                  WasheGameData gameData, WasheOperateResult result, WasheUseSkillParam param) {

        // 技能参数
        WasheCardConfig cardConfig = config.getCardConfigMap().get(eWasheSkillType.Card_03.getValue());
        long paramCount = cardConfig.getSkillParamList().get(0);

        // 统计颜色
        Map<Integer, Integer> colorCountMap = new HashMap<>();
        List<List<WasheBlock>> blockList = gameData.getBlockList();
        for (List<WasheBlock> list : blockList) {
            for (WasheBlock block : list) {
                colorCountMap.put(block.getColor(), colorCountMap.getOrDefault(block.getColor(), 0) + 1);
            }
        }

        // 找颜色数量最多的颜色
        int chooseColor = eWasheColorType.Green.getValue();
        int chooseColorCount = 0;
        for (Map.Entry<Integer, Integer> entry : colorCountMap.entrySet()) {
            int color = entry.getKey();
            int count = entry.getValue();
            if (color != 0 && color != eWasheColorType.Red.getValue() && color != eWasheColorType.Blue.getValue()) {
                if (count > chooseColorCount) {
                    chooseColor = color;
                    chooseColorCount = count;
                }
            }
        }

        // 技能不会生效到的颜色
        Set<Integer> exceptColor = new HashSet<>();
        exceptColor.add(chooseColor);
        exceptColor.add(param.getSide() == 1 ? eWasheColorType.Red.getValue() : eWasheColorType.Blue.getValue());

        // 可使用格子
        List<WasheBlock> all = new ArrayList<>();
        for (List<WasheBlock> list : blockList) {
            for (WasheBlock block : list) {
                if (block.getBlockType() == eWasheBlockType.Normal && !exceptColor.contains(block.getColor())) {
                    all.add(block);
                }
            }
        }

        // 选择格子
        Collections.shuffle(all, random);
        Set<WasheBlock> set = new HashSet<>();
        for (WasheBlock block : all) {
            if (set.size() >= paramCount) {
                break;
            }
            block.setColor(chooseColor);
            WasheSceneLogic.scene_12_checkEffectChange(block, gameData);
            set.add(block);
        }

        // 技能效果
        WasheOperateEffect operateEffect = new WasheOperateEffect(eWasheSkillType.Card_03, 1);
        operateEffect.setParam(chooseColor);
        operateEffect.setBlockList(new ArrayList<>(set));
        result.addEffect(operateEffect);
        result.addEffect(new WasheOperateEffect(eWasheSkillType.Card_03, 0)); // 添加技能效果结束

        return new HashSet<>();
    }

    private static Set<WasheBlock> handleSkill_04(WasheConfig config, Random random,
                                                  WasheGameData gameData, WasheOperateResult result) {

        // 技能配置
        WasheCardConfig cardConfig = config.getCardConfigMap().get(eWasheSkillType.Card_04.getValue());
        long paramCount = cardConfig.getSkillParamList().get(0);

        // 可使用格子
        List<List<WasheBlock>> blockList = gameData.getBlockList();
        List<WasheBlock> all = new ArrayList<>();
        for (List<WasheBlock> list : blockList) {
            for (WasheBlock block : list) {
                if (block.getBlockType() == eWasheBlockType.Normal) {
                    all.add(block);
                }
            }
        }

        // 选择格子
        Collections.shuffle(all, random);
        Set<WasheBlock> set = new HashSet<>();
        for (WasheBlock block : all) {
            if (set.size() >= paramCount) {
                break;
            }
            int index = random.nextInt(4000) / 1000;
            block.setBlockType(index == 1 ? eWasheBlockType.Hang
                    : index == 2 ? eWasheBlockType.Lie
                    : index == 3 ? eWasheBlockType.DiLei
                    : eWasheBlockType.LiuXing);
            WasheSceneLogic.scene_12_checkEffectChange(block, gameData);
            set.add(block);
        }

        // 自爆炸弹格子
        Set<WasheBlock> set2 = new HashSet<>();
        for (List<WasheBlock> list : blockList) {
            for (WasheBlock block : list) {
                if (block.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL_BOMB
                        || block.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_SPECIAL_BOMB) {
                    set2.add(block);
                }
            }
        }

        // 技能效果
        WasheOperateEffect effect = new WasheOperateEffect(eWasheSkillType.Card_04, 1);
        effect.setBlockList(new ArrayList<>(set));
        result.addEffect(effect);
        WasheOperateEffect effect2 = new WasheOperateEffect(eWasheSkillType.Card_04, 2);
        effect2.setBlockList(new ArrayList<>(set2));
        result.addEffect(effect2);
        result.addEffect(new WasheOperateEffect(eWasheSkillType.Card_04, 0));

        return set2;
    }

    private static Set<WasheBlock> handleSkill_05(Random random,
                                                  WasheGameData gameData, WasheOperateResult result) {

        List<List<WasheBlock>> blockList = gameData.getBlockList();

        // 随机位置
        int lineIndex = random.nextInt(blockList.size() - 2) + 1;
        int colIndex = random.nextInt(blockList.get(0).size() - 2) + 1;
        WasheBlock block = blockList.get(lineIndex).get(colIndex);

        // 选择消除的方块
        Set<WasheBlock> all = new HashSet<>();
        List<WasheBlock> list1 = new ArrayList<>(); // 左
        List<WasheBlock> list2 = new ArrayList<>(); // 右
        for (List<WasheBlock> list : blockList) {
            for (WasheBlock tmpBlock : list) {
                if (WasheGameLogic.isBaseFourBigType(tmpBlock)) {
                    if (tmpBlock.getX() != block.getX() && tmpBlock.getY() != block.getY()) {
                        int subY = tmpBlock.getY() - block.getY();
                        int subX = tmpBlock.getX() - block.getX();
                        if (Math.abs(subY) == Math.abs(subX)) { // 斜方向上的给咱
                            if (subY * subX < 0) {
                                list1.add(tmpBlock);
                            } else {
                                list2.add(tmpBlock);
                            }
                            all.add(tmpBlock);
                        }
                    }
                }
            }
        }
        all.add(block);
        list1.add(block);
        list2.add(block);

        // 效果
        WasheOperateEffect effect1 = new WasheOperateEffect(eWasheSkillType.Card_05, 1);
        effect1.setBlockList(Collections.singletonList(block));
        result.addEffect(effect1);
        WasheOperateEffect effect2 = new WasheOperateEffect(eWasheSkillType.Card_05, 3);
        effect2.setBlockList(list1);
        result.addEffect(effect2);
        WasheOperateEffect effect3 = new WasheOperateEffect(eWasheSkillType.Card_05, 2);
        effect3.setBlockList(Collections.singletonList(block));
        result.addEffect(effect3);
        WasheOperateEffect effect4 = new WasheOperateEffect(eWasheSkillType.Card_05, 3);
        effect4.setBlockList(list2);
        result.addEffect(effect4);
        result.addEffect(new WasheOperateEffect(eWasheSkillType.Card_05, 0));
        return all;
    }

    private static Set<WasheBlock> handleSkill_06(WasheConfig config, Random random,
                                                  WasheGameData gameData, WasheOperateResult result, WasheUseSkillParam param) {
        // 技能配置
        WasheCardConfig cardConfig = config.getCardConfigMap().get(eWasheSkillType.Card_06.getValue());
        List<Long> paramList = cardConfig.getSkillParamList();

        List<List<WasheBlock>> blockList = gameData.getBlockList();

        // 选择方块
        if (!WasheGameLogic.isXyExist(blockList, param.getX(), param.getY())) {
            return new HashSet<>();
        }

        WasheBlock block = blockList.get(param.getY()).get(param.getX());
        Set<WasheBlock> all = new HashSet<>();
        List<List<WasheBlock>> gifList = new ArrayList<>();
        List<WasheBlock> checkBlockList = new ArrayList<>();

        // 添加基础弥漫格子
        if (WasheGameLogic.isBaseFourBigType(block)) {
            all.add(block);
        }
        gifList.add(new ArrayList<>());
        gifList.get(0).add(block);
        checkBlockList.add(block);

        // 上右下左
        int[][] xyArr = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};

        // 后续弥漫
        for (int i = 0; i < paramList.size(); i++) {
            List<WasheBlock> nextCheckBlockList = new ArrayList<>();
            for (WasheBlock checkBlock : checkBlockList) {
                for (int[] xy : xyArr) {
                    int tmpX = checkBlock.getX() + xy[0];
                    int tmpY = checkBlock.getY() + xy[1];
                    if (WasheGameLogic.isXyExist(blockList, tmpX, tmpY)) {
                        WasheBlock tmpBlock = blockList.get(tmpY).get(tmpX);
                        if (WasheGameLogic.isBaseFourBigType(tmpBlock)) {
                            if (!all.contains(tmpBlock) && random.nextInt(1000) < paramList.get(i)) {
                                nextCheckBlockList.add(tmpBlock);
                            }
                        }
                    }
                }
            }
            gifList.add(nextCheckBlockList);
            all.addAll(nextCheckBlockList);
            checkBlockList = nextCheckBlockList;
            if (checkBlockList.isEmpty()) {
                break;
            }
        }

        // 技能效果
        WasheOperateEffect effect1 = new WasheOperateEffect(eWasheSkillType.Card_06, 1);
        effect1.setBlockList(Collections.singletonList(block));
        result.addEffect(effect1);
        for (int i = 0; i < gifList.size(); i++) {
            WasheOperateEffect effect2 = new WasheOperateEffect(eWasheSkillType.Card_06, 2);
            effect2.setBlockList(gifList.get(i));
            result.addEffect(effect2);
        }
        result.addEffect(new WasheOperateEffect(eWasheSkillType.Card_06, 3));
        result.addEffect(new WasheOperateEffect(eWasheSkillType.Card_06, 0));

        return all;
    }

    private static Set<WasheBlock> handleSkill_07(WasheConfig config, Random random,
                                                  WasheGameData gameData, WasheOperateResult result) {
        // 技能配置
        WasheCardConfig cardConfig = config.getCardConfigMap().get(eWasheSkillType.Card_07.getValue());
        long chooseNum = cardConfig.getSkillParamList().get(0);
        int maxRandomScore = 6;

        List<List<WasheBlock>> blockList = gameData.getBlockList();

        // 可随机方块
        List<WasheBlock> all = new ArrayList<>();
        for (List<WasheBlock> list : blockList) {
            for (WasheBlock block : list) {
                if (block.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL
                        && block.getColor() != eWasheColorType.Red.getValue()
                        && block.getColor() != eWasheColorType.Blue.getValue()) {
                    all.add(block);
                }
            }
        }

        // 随机方块出来
        Set<WasheBlock> chooseSet = new HashSet<>();
        for (int i = 0; i < chooseNum && !all.isEmpty(); i++) {
            int index = random.nextInt(all.size());
            WasheBlock block = all.remove(index);

            WasheBlockEffect effect = new WasheBlockEffect(eWasheBlockEffectType.Skill_7);
            effect.setEffectValue(random.nextInt(maxRandomScore) + 1); // 随机分数出来
            block.addEffect(effect);

            chooseSet.add(block);
        }

        // 技能效果
        WasheOperateEffect effect = new WasheOperateEffect(eWasheSkillType.Card_07, 1);
        effect.setBlockList(new ArrayList<>(chooseSet));
        result.addEffect(effect);
        result.addEffect(new WasheOperateEffect(eWasheSkillType.Card_07, 0));
        return chooseSet;
    }

    private static Set<WasheBlock> handleSkill_08(WasheGameData gameData, WasheOperateResult result) {

        List<List<WasheBlock>> blockList = gameData.getBlockList();

        Set<WasheBlock> movedSet = new HashSet<>();

        for (int times = 0; times < 10; times++) { // 最多检查10轮，如果本轮没有可移动的，下面会break
            int curSize = movedSet.size();

            for (int y = 0; y < blockList.size(); y++) {
                for (int x = 0; x < blockList.get(y).size(); x++) {

                    WasheBlock block1 = blockList.get(y).get(x);
                    if (movedSet.contains(block1)) {
                        continue;
                    }

                    // 跟右边交换
                    int x2 = x + 1;
                    int y2 = y;
                    if (WasheGameLogic.isXyExist(blockList, x2, y2) && !movedSet.contains(blockList.get(y2).get(x2))) {
                        WasheBlock block2 = blockList.get(y2).get(x2);
                        WasheGameLogic.exchangeBlock(blockList, x, y, x2, y2, null);
                        List<WasheBlock> list1 = getSameColorList(blockList, block1);
                        List<WasheBlock> list2 = getSameColorList(blockList, block2);
                        if (list1 != null || list2 != null) {

                            Set<WasheBlock> set = new HashSet<>();
                            if (list1 != null) set.addAll(list1);
                            if (list2 != null) set.addAll(list2);

                            movedSet.addAll(set);
                            movedSet.add(block1);
                            movedSet.add(block2);

                            WasheOperateEffect effect1 = new WasheOperateEffect(eWasheSkillType.Card_08, 1);
                            effect1.addBlock(block1);
                            effect1.addBlock(block2);
                            result.addEffect(effect1);

                            WasheOperateEffect effect2 = new WasheOperateEffect(eWasheEffectType.HighLight);
                            effect2.setBlockList(new ArrayList<>(set));
                            result.addEffect(effect2);
                            continue;
                        } else {
                            WasheGameLogic.exchangeBlock(blockList, x, y, x2, y2, null);
                        }
                    }

                    // 跟上边交换
                    x2 = x;
                    y2 = y + 1;
                    if (WasheGameLogic.isXyExist(blockList, x2, y2) && !movedSet.contains(blockList.get(y2).get(x2))) {
                        WasheBlock block2 = blockList.get(y2).get(x2);
                        WasheGameLogic.exchangeBlock(blockList, x, y, x2, y2, null);
                        List<WasheBlock> list1 = getSameColorList(blockList, block1);
                        List<WasheBlock> list2 = getSameColorList(blockList, block2);
                        if (list1 != null || list2 != null) {

                            Set<WasheBlock> set = new HashSet<>();
                            if (list1 != null) set.addAll(list1);
                            if (list2 != null) set.addAll(list2);

                            movedSet.addAll(set);
                            movedSet.add(block1);
                            movedSet.add(block2);

                            WasheOperateEffect effect1 = new WasheOperateEffect(eWasheSkillType.Card_08, 1);
                            effect1.addBlock(block1);
                            effect1.addBlock(block2);
                            result.addEffect(effect1);

                            WasheOperateEffect effect2 = new WasheOperateEffect(eWasheEffectType.HighLight);
                            effect2.setBlockList(new ArrayList<>(set));
                            result.addEffect(effect2);
                            continue;
                        } else {
                            WasheGameLogic.exchangeBlock(blockList, x, y, x2, y2, null);
                        }
                    }

                }
            }

            if (curSize == movedSet.size()) {
                break;
            }
        }

        result.addEffect(new WasheOperateEffect(eWasheSkillType.Card_08, 0));
        return new HashSet<>();
    }

    private static Set<WasheBlock> handleSkill_09(Random random,
                                                  WasheGameData gameData, WasheOperateResult result, WasheUseSkillParam param) {

        List<List<WasheBlock>> blockList = gameData.getBlockList();

        // 移动
        WasheGameLogic.exchangeBlock(gameData.getBlockList(), param.getX(), param.getY(), param.getToX(), param.getToY(), result);

        // 获取同色消除格子
        Set<WasheBlock> set = new HashSet<>();
        for (List<WasheBlock> list : blockList) {
            for (WasheBlock block : list) {
                if (WasheGameLogic.canSameColorEliminate(blockList, block)) {
                    set.add(block);
                }
            }
        }
        if (set.isEmpty()) {
            return new HashSet<>();
        }

        // 消除组分类（移除触发的消除，同色的肯定是一起消除的）
        Map<Integer, Set<WasheBlock>> tmpMap = new HashMap<>(); // 按颜色分
        for (WasheBlock tmpBlock : set) {
            tmpMap.putIfAbsent(tmpBlock.getColor(), new HashSet<>());
            tmpMap.get(tmpBlock.getColor()).add(tmpBlock);
        }

        // 拿一下覆盖长度最长的消除组
        int maxLen = 0;
        boolean maxIsHeng = false;
        Set<WasheBlock> maxSet = new HashSet<>();
        for (Set<WasheBlock> tmpSet : tmpMap.values()) {
            Set<Integer> xSet = new HashSet<>();
            Set<Integer> ySet = new HashSet<>();
            for (WasheBlock block : tmpSet) {
                xSet.add(block.getX());
                ySet.add(block.getY());
            }

            // 看一下横向格子多还是纵向格子多
            boolean isHeng = xSet.size() > ySet.size();
            if (xSet.size() == ySet.size()) {
                isHeng = random.nextInt(1000) < 500;
            }
            int len = isHeng ? xSet.size() : ySet.size();

            // 跟最大组比一下
            if (len > maxLen || len == maxLen && random.nextInt(1000) < 500) {
                maxLen = len;
                maxIsHeng = isHeng;
                maxSet = tmpSet;
            }
        }

        // 拿消除组触发效果的格子
        Map<Integer, List<WasheBlock>> listMap = new HashMap<>(); // Map<横/纵坐标，处于该行/列的格子>
        for (WasheBlock block : maxSet) {
            int key = maxIsHeng ? block.getY() : block.getX();
            listMap.putIfAbsent(key, new ArrayList<>());
            listMap.get(key).add(block);
        }
        List<WasheBlock> maxList = new ArrayList<>(); // 单行/列数量最多的list
        for (Map.Entry<Integer, List<WasheBlock>> entry : listMap.entrySet()) {
            if (entry.getValue().size() > maxList.size()) {
                maxList = entry.getValue();
            }
        }

        // 找下触发后消除的范围
        Set<WasheBlock> firstBlock = new HashSet<>();
        for (WasheBlock block : maxList) {
            if (maxIsHeng) {
                for (int tempY = block.getY() - 3; tempY <= block.getY() + 3; tempY++) {
                    if (WasheGameLogic.isXyExist(blockList, block.getX(), tempY)) {
                        firstBlock.add(blockList.get(tempY).get(block.getX()));
                    }
                }
            } else {
                for (int tempX = block.getX() - 3; tempX <= block.getX() + 3; tempX++) {
                    if (WasheGameLogic.isXyExist(blockList, tempX, block.getY())) {
                        firstBlock.add(blockList.get(block.getY()).get(tempX));
                    }
                }
            }
        }
        WasheGameLogic.removeNoBaseFourBigType(firstBlock);

        // 添加效果（移动效果前面加了）
        WasheOperateEffect effect = new WasheOperateEffect(eWasheSkillType.Card_09, maxIsHeng ? 2 : 1); // 1横向消除，2竖向消除，格子横向排列时要竖向消除
        effect.setBlockList(maxList);
        result.addEffect(effect);
        result.addEffect(new WasheOperateEffect(eWasheSkillType.Card_09, 0));

        return firstBlock;
    }

    private static Set<WasheBlock> handleSkill_10(WasheGameData gameData, WasheOperateResult result, WasheUseSkillParam param) {
        List<List<WasheBlock>> blockList = gameData.getBlockList();

        // 选择的位置
        int x = param.getX();
        int y = param.getY();
        WasheBlock block = blockList.get(y).get(x);

        // 选择的方块
        Set<WasheBlock> all = new HashSet<>();
        List<WasheBlock> sameYList = blockList.get(y);
        all.addAll(sameYList);
        for (List<WasheBlock> sameXList : blockList) {
            all.add(sameXList.get(x));
        }
        WasheGameLogic.removeNoBaseFourBigType(all);

        // 技能效果
        WasheOperateEffect effect1 = new WasheOperateEffect(eWasheSkillType.Card_10, 1);
        effect1.setBlockList(Collections.singletonList(block));
        result.addEffect(effect1);
        WasheOperateEffect effect2 = new WasheOperateEffect(eWasheEffectType.Light);
        effect2.setBlockList(new ArrayList<>(all));
        result.addEffect(effect2);
        result.addEffect(new WasheOperateEffect(eWasheSkillType.Card_10, 0));

        return all;
    }

    private static Set<WasheBlock> handleSkill_11(WasheGameData gameData, WasheOperateResult result,
                                                  WasheUseSkillParam param) {

        List<List<WasheBlock>> blockList = gameData.getBlockList();

        // 选择方块拿颜色
        if (!WasheGameLogic.isXyExist(blockList, param.getX(), param.getY())) {
            return new HashSet<>();
        }
        WasheBlock block = blockList.get(param.getY()).get(param.getX());
        int color = block.getColor();
        if (color == 0) {
            return new HashSet<>();
        }

        // 红釉青花特殊处理
        WasheSceneLogic.scene_08_changeColor(gameData, color);

        // 消除同色
        Set<WasheBlock> all = new HashSet<>();
        for (List<WasheBlock> list : blockList) {
            for (WasheBlock tmpBlock : list) {
                if (tmpBlock.getColor() == color) {
                    if (tmpBlock.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL
                            || tmpBlock.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL_BOMB
                            || tmpBlock.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_SPECIAL) {
                        all.add(tmpBlock);
                    }
                }
            }
        }

        // 技能效果
        WasheOperateEffect effect = new WasheOperateEffect(eWasheSkillType.Card_11, 1);
        effect.setBlockList(new ArrayList<>(all));
        result.addEffect(effect);
        result.addEffect(new WasheOperateEffect(eWasheSkillType.Card_11, 0));

        return all;
    }

    private static Set<WasheBlock> handleSkill_12(WasheConfig config, Random random, WasheGameData gameData, WasheOperateResult result) {

        List<List<WasheBlock>> blockList = gameData.getBlockList();

        // 配置
        WasheCardConfig cardConfig = config.getCardConfigMap().get(eWasheSkillType.Card_12.getValue());
        long lineCount = cardConfig.getSkillParamList().get(0);
        lineCount = Math.min(lineCount, blockList.size());

        // 随机取行号
        List<Integer> allIndexList = new ArrayList<>();
        for (int i = 0; i < blockList.size(); i++) {
            allIndexList.add(i);
        }
        List<Integer> chooseIndexList = new ArrayList<>();
        for (int i = 0; i < lineCount; i++) {
            int index = allIndexList.remove(random.nextInt(allIndexList.size()));
            chooseIndexList.add(index);
        }

        // 选中的格子
        Set<WasheBlock> set = new HashSet<>();
        for (int index : chooseIndexList) {
            set.addAll(blockList.get(index));
        }
        WasheGameLogic.removeNoBaseFourBigType(set);

        // 技能效果
        WasheOperateEffect effect = new WasheOperateEffect(eWasheSkillType.Card_12, 1);
        effect.setBlockList(new ArrayList<>(set));
        result.addEffect(effect);
        result.addEffect(new WasheOperateEffect(eWasheSkillType.Card_12, 0));
        return set;
    }

    public static Set<WasheBlock> handleSkill_13(WasheConfig config, Random random,
                                                 WasheGameData gameData, WasheOperateResult result, boolean isUseCard) {

        // 技能配置
        WasheCardConfig cardConfig = config.getCardConfigMap().get(eWasheSkillType.Card_13.getValue());
        long paramCount = cardConfig.getSkillParamList().get(0);

        // 可使用格子
        List<List<WasheBlock>> blockList = gameData.getBlockList();
        List<WasheBlock> all = new ArrayList<>();
        for (List<WasheBlock> list : blockList) {
            for (WasheBlock block : list) {
                if (block.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL ||
                        block.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_SPECIAL ||
                        block.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL_BOMB ||
                        block.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_SPECIAL_BOMB) {
                    all.add(block);
                }
            }
        }

        // 选择格子
        Collections.shuffle(all, random);
        Set<WasheBlock> set = new HashSet<>();
        for (WasheBlock block : all) {
            if (set.size() >= paramCount) {
                break;
            }
            block.addEffect(new WasheBlockEffect(eWasheBlockEffectType.Skill_13));
            set.add(block);
        }

        // 添加效果
        WasheOperateEffect effect = new WasheOperateEffect(eWasheEffectType.UpdateBlock);
        effect.setBlockList(new ArrayList<>(set));
        result.addEffect(effect);
        if (isUseCard) { // 移动结束也会触发这个，次数不能有这个结束表现
            result.addEffect(new WasheOperateEffect(eWasheSkillType.Card_13, 0));
        }

        return new HashSet<>();
    }

    public static Set<WasheBlock> handleSkill_14(WasheConfig config, Random random,
                                                 WasheGameData gameData, WasheOperateResult result, WasheUseSkillParam param) {

        List<List<WasheBlock>> blockList = gameData.getBlockList();

        // 技能配置
        WasheCardConfig cardConfig = config.getCardConfigMap().get(eWasheSkillType.Card_14.getValue());
        long moveTimes = cardConfig.getSkillParamList().get(0);

        // 可移动格子
        int blueColor = param.getSide() == 1 ? eWasheColorType.Red.getValue() : eWasheColorType.Blue.getValue();
        List<WasheBlock> moveList = new ArrayList<>();
        for (List<WasheBlock> list : blockList) {
            for (WasheBlock block : list) {
                if (block.getColor() == blueColor) {
                    if (block.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL
                            || block.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL_BOMB
                            || block.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_SPECIAL) {
                        moveList.add(block);
                    }
                }
            }
        }

        // 存结果
        Set<WasheBlock> allMoveSet = new HashSet<>();
        List<List<WasheBlock>> showList2 = new ArrayList<>(); // 【士】
        List<List<WasheBlock>> showList3 = new ArrayList<>(); // 【马】
        List<List<WasheBlock>> showList4 = new ArrayList<>(); // 【象】
        List<WasheBlock> needMoveList2 = new ArrayList<>();
        List<WasheBlock> needMoveList3 = new ArrayList<>();
        List<WasheBlock> needMoveList4 = new ArrayList<>();

        // 先随机变成马、象、士
        for (WasheBlock block : moveList) {
            int type = random.nextInt(3) + 2;
            if (type == 2) needMoveList2.add(block);
            if (type == 3) needMoveList3.add(block);
            if (type == 4) needMoveList4.add(block);
        }

        // 棋子移动相对坐标
        int[][] movePosArr2 = new int[][]{
                {-1, 1}, {1, 1}, {-1, -1}, {1, -1}};
        int[][] movePosArr3 = new int[][]{
                {-1, 2}, {1, 2}, {-2, 1}, {2, 1}, {-2, -1}, {2, -1}, {-1, -2}, {1, -2}};
        int[][] movePosArr4 = new int[][]{
                {-2, 2}, {2, 2}, {-2, -2}, {2, -2}};

        // 开始移动
        for (int i = 0; i < moveTimes; i++) {

            // 本次移动的点，2个一组
            List<WasheBlock> curMoveList2 = new ArrayList<>();
            List<WasheBlock> curMoveList3 = new ArrayList<>();
            List<WasheBlock> curMoveList4 = new ArrayList<>();
            // 记录下次移动起始点
            List<WasheBlock> nextNeedMoveList2 = new ArrayList<>();
            List<WasheBlock> nextNeedMoveList3 = new ArrayList<>();
            List<WasheBlock> nextNeedMoveList4 = new ArrayList<>();

            // 本轮移动过的位置
            Set<WasheBlock> roundMoveSet = new HashSet<>();

            // 3马、4象、2士    按顺序移动
            moveChess(random, blockList, allMoveSet, needMoveList3, movePosArr3, curMoveList3, nextNeedMoveList3, roundMoveSet);
            moveChess(random, blockList, allMoveSet, needMoveList4, movePosArr4, curMoveList4, nextNeedMoveList4, roundMoveSet);
            moveChess(random, blockList, allMoveSet, needMoveList2, movePosArr2, curMoveList2, nextNeedMoveList2, roundMoveSet);

            // 记录结果
            showList2.add(curMoveList2);
            showList3.add(curMoveList3);
            showList4.add(curMoveList4);

            // 下一轮移动的
            needMoveList2 = nextNeedMoveList2;
            needMoveList3 = nextNeedMoveList3;
            needMoveList4 = nextNeedMoveList4;
        }

        // 结果
        result.addEffect(new WasheOperateEffect(eWasheSkillType.Card_14, 1));
        for (int i = 0; i < showList2.size(); i++) {
            List<WasheBlock> show2 = showList2.get(i);
            List<WasheBlock> show3 = showList3.get(i);
            List<WasheBlock> show4 = showList4.get(i);

            WasheOperateEffect effect2 = new WasheOperateEffect(eWasheSkillType.Card_14, 2);
            effect2.setBlockList(show2);
            WasheOperateEffect effect3 = new WasheOperateEffect(eWasheSkillType.Card_14, 3);
            effect3.setBlockList(show3);
            WasheOperateEffect effect4 = new WasheOperateEffect(eWasheSkillType.Card_14, 4);
            effect4.setBlockList(show4);

            result.addEffect(effect3);
            result.addEffect(effect4);
            result.addEffect(effect2);
            result.addEffect(new WasheOperateEffect(eWasheSkillType.Card_14, 5));
        }
        result.addEffect(new WasheOperateEffect(eWasheSkillType.Card_14, 0));

        return allMoveSet;
    }

    private static Set<WasheBlock> handleSkill_15(WasheConfig config, Random random,
                                                  WasheGameData gameData, WasheOperateResult result) {

        // 取颜色数量
        WasheCardConfig cardConfig = config.getCardConfigMap().get(eWasheSkillType.Card_15.getValue());
        long count = cardConfig.getSkillParamList().get(0);

        // 取红色、蓝色外的颜色，打乱
        List<Integer> colorList = new ArrayList<>();
        for (int color = 1; color <= config.getColorNum(); color++) {
            if (color != eWasheColorType.Red.getValue() && color != eWasheColorType.Blue.getValue()) {
                colorList.add(color);
            }
        }
        Collections.shuffle(colorList, random);

        // 拿随机到的颜色
        Set<Integer> colorSet = new HashSet<>();
        for (Integer color : colorList) {
            if (colorSet.size() >= count) {
                break;
            }
            colorSet.add(color);
        }

        // 拿消除的方块
        Set<WasheBlock> set = new HashSet<>();
        for (List<WasheBlock> blockList : gameData.getBlockList()) {
            for (WasheBlock block : blockList) {
                if (block.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL
                        && colorSet.contains(block.getColor())) {
                    set.add(block);
                }
            }
        }

        // 添加效果
        WasheOperateEffect operateEffect = new WasheOperateEffect(eWasheSkillType.Card_15, 1);
        operateEffect.setBlockList(new ArrayList<>(set));
        result.addEffect(operateEffect);
        result.addEffect(new WasheOperateEffect(eWasheSkillType.Card_15, 0));

        return set;
    }

    private static Set<WasheBlock> handleSkill_16(WasheConfig config, WasheGameData gameData, WasheOperateResult result, WasheUserGameData userGameData, WasheUseSkillParam param, Random random, int roomRound, int turnPlayer) {
        List<List<WasheBlock>> blockList = gameData.getBlockList();

        // 【自动选颜色】
        List<WasheSkill16Color> skill16ColorList = new ArrayList<>();
        int blue = param.getSide() == 1 ? eWasheColorType.Red.getValue() : eWasheColorType.Blue.getValue();
        for (int tmpColor = 1; tmpColor <= 6; tmpColor++) {
            // 不能选蓝色
            if (tmpColor == blue) {
                continue;
            }
            // 每种颜色看看多少4连，能变色多少个
            int bombNum = 0;
            int sumSubValue = 0;
            for (int x = 0; x < blockList.get(0).size(); x++) {
                int topY = 0;
                int bottomY = blockList.size() - 1;
                // 从下往上找
                for (int y = 0; y < blockList.size(); y++) {
                    WasheBlock block = blockList.get(y).get(x);
                    if (block.getColor() == tmpColor) {
                        if (block.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL
                                || block.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL_BOMB) {
                            bottomY = y;
                            break;
                        }
                    }
                }
                // 从上往下找
                for (int y = blockList.size() - 1; y >= 0; y--) {
                    WasheBlock block = blockList.get(y).get(x);
                    if (block.getColor() == tmpColor) {
                        if (block.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL
                                || block.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL_BOMB) {
                            topY = y;
                            break;
                        }
                    }
                }
                int subValue = topY - bottomY;
                if (subValue >= 3) {
                    bombNum++;
                }
                if (subValue > 0) {
                    sumSubValue += subValue;
                }
            }
            skill16ColorList.add(new WasheSkill16Color(tmpColor, bombNum, sumSubValue));
        }
        Optional<WasheSkill16Color> first = skill16ColorList.stream().min(new Comparator<WasheSkill16Color>() {
            @Override
            public int compare(WasheSkill16Color o1, WasheSkill16Color o2) {
                if (o2.getBombNum() != o1.getBombNum()) {
                    return Integer.compare(o2.getBombNum(), o1.getBombNum());
                }
                if (o2.getSumSubValue() != o1.getSumSubValue()) {
                    return Integer.compare(o2.getSumSubValue(), o1.getSumSubValue());
                }
                return Integer.compare(o2.getColorWeight(), o1.getColorWeight());
            }
        });
        int color = first.get().getColor();

        // 拿变色的格子
        Set<WasheBlock> set = new HashSet<>();
        for (int x = 0; x < blockList.get(0).size(); x++) {
            int topY = -1;
            for (int y = blockList.size() - 1; y >= 0; y--) {
                WasheBlock tmpBlock = blockList.get(y).get(x);
                if (tmpBlock.getColor() == color) {
                    if (tmpBlock.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL
                            || tmpBlock.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL_BOMB) {
                        topY = tmpBlock.getY();
                        break;
                    }
                }
            }
            int bottomY = blockList.size();
            for (int y = 0; y < blockList.size(); y++) {
                WasheBlock tmpBlock = blockList.get(y).get(x);
                if (tmpBlock.getColor() == color) {
                    if (tmpBlock.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL
                            || tmpBlock.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL_BOMB) {
                        bottomY = tmpBlock.getY();
                        break;
                    }
                }
            }
            if (bottomY < topY) {
                set.add(blockList.get(bottomY).get(x));
                set.add(blockList.get(topY).get(x));
            }
            for (int y = bottomY + 1; y < topY; y++) {
                WasheBlock tmpBlock = blockList.get(y).get(x);
                if (tmpBlock.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL
                        || tmpBlock.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL_BOMB) {
                    tmpBlock.setColor(color);
                    WasheSceneLogic.scene_12_checkEffectChange(tmpBlock, gameData);
                    set.add(tmpBlock);
                }
            }
        }

        // 技能效果
        WasheOperateEffect effect = new WasheOperateEffect(eWasheSkillType.Card_16, 1);
        effect.setBlockList(new ArrayList<>(set));
        result.addEffect(effect);
        // 消除
        WasheGameLogic.bigEliminate(config, gameData, userGameData, null, new HashSet<>(), result, random, -1, roomRound, turnPlayer);
        // 随机一个炸弹爆炸
        List<WasheBlock> bombList = new ArrayList<>();
        for (List<WasheBlock> list : blockList) {
            for (WasheBlock block : list) {
                if (block.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL_BOMB) {
                    bombList.add(block);
                }
            }
        }
        WasheBlock block = null;
        if (bombList.size() > 0) {
            block = bombList.get(random.nextInt(bombList.size()));
            WasheOperateEffect effect2 = new WasheOperateEffect(eWasheSkillType.Card_16, 2);
            effect2.addBlock(block);
            result.addEffect(effect2);
        }
        // 技能效果
        result.addEffect(new WasheOperateEffect(eWasheSkillType.Card_16, 0));

        Set<WasheBlock> tmpSet = new HashSet<>();
        if (block != null) {
            tmpSet.add(block);
        }
        return tmpSet;
    }

    private static Set<WasheBlock> handleSkill_17(WasheConfig config, Random random, WasheGameData gameData, WasheOperateResult result) {
        List<List<WasheBlock>> blockList = gameData.getBlockList();

        // 配置
        WasheCardConfig cardConfig = config.getCardConfigMap().get(eWasheSkillType.Card_17.getValue());
        long createNum = cardConfig.getSkillParamList().get(0);
        long boomNum = cardConfig.getSkillParamList().get(1);

        // 所有可用格子
        List<WasheBlock> all = new ArrayList<>();
        for (List<WasheBlock> list : blockList) {
            for (WasheBlock block : list) {
                if (block.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL) {
                    all.add(block);
                }
            }
        }

        // 随机格子
        List<WasheBlock> replaceList = new ArrayList<>();
        List<WasheBlock> boomList = new ArrayList<>();
        for (int i = 0; i < createNum; i++) {

            WasheBlock block = all.remove(random.nextInt(all.size()));

            block.setBlockType(eWasheBlockType.Rocket);
            WasheSceneLogic.scene_12_checkEffectChange(block, gameData);
            block.setDirection(eWasheDirectionType.getType(random.nextInt(4) + 1));

            replaceList.add(block);
            if (boomList.size() < boomNum) {
                boomList.add(block);
            }
        }

        // 技能效果
        WasheOperateEffect effect = new WasheOperateEffect(eWasheSkillType.Card_17, 1);
        effect.setBlockList(replaceList);
        result.addEffect(effect);
        WasheOperateEffect effect2 = new WasheOperateEffect(eWasheSkillType.Card_17, 2);
        effect2.setBlockList(boomList);
        result.addEffect(effect2);
        result.addEffect(new WasheOperateEffect(eWasheSkillType.Card_17, 0));

        return new HashSet<>(boomList);
    }


    private static Set<WasheBlock> handleSkill_18(WasheConfig config, Random random,
                                                  WasheGameData gameData, WasheOperateResult result) {

        List<List<WasheBlock>> blockList = gameData.getBlockList();

        int chooseColNum = 3;

        // 统计每列普通炸弹
        Map<Integer, WasheSkill18X> map = new HashMap<>();
        for (int x = 0; x < config.getBlockListWidth(); x++) {
            map.put(x, new WasheSkill18X(x));
        }
        for (List<WasheBlock> blocks : blockList) {
            for (WasheBlock block : blocks) {
                if (block.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL_BOMB) {
                    WasheSkill18X washeSkill18X = map.get(block.getX());
                    washeSkill18X.setNum(washeSkill18X.getNum() + 1);
                }
            }
        }
        List<WasheSkill18X> list = new ArrayList<>(map.values());
        Collections.shuffle(list, random);
        list.sort(Comparator.comparing(WasheSkill18X::getNum).reversed());

        // 抽几个出来
        List<Integer> chooseList = new ArrayList<>();
        for (int loop = 0; loop < 99 && chooseList.size() < chooseColNum && list.size() > 0; loop++) {

            List<WasheSkill18X> sameNumList = new ArrayList<>();
            int num = list.get(0).getNum();
            for (int i = 0; i < list.size(); i++) {
                WasheSkill18X tmp = list.get(i);
                if (tmp.getNum() == num) {
                    sameNumList.add(tmp);
                } else {
                    break;
                }
            }

            int chooseX = sameNumList.get(random.nextInt(sameNumList.size())).getX();
            chooseList.add(chooseX);

            for (int i = 0; i < list.size(); i++) {
                int tmpX = list.get(i).getX();
                if (Math.abs(tmpX - chooseX) <= 1) { // 移除自己，移除相邻两列
                    list.remove(i--);
                }
            }
        }
        chooseList.sort(Comparator.comparing(Integer::intValue));

        // 方向
        List<Integer> directionList = new ArrayList<>();
        for (int i = 0; i < chooseList.size(); i++) { // 初始化一个0
            directionList.add(0);
        }
        if (chooseList.get(0) == 0) { // 特殊情况先处理
            directionList.set(0, 1);
        }
        if (chooseList.get(chooseList.size() - 1) == config.getBlockListWidth() - 1) {
            directionList.set(chooseList.size() - 1, -1);
        }
        Set<Integer> noSet = new HashSet<>();
        for (int i = 0; i < chooseList.size(); i++) { // 记录无法选中的x值
            int choose = chooseList.get(i);
            noSet.add(choose);

            int direction = directionList.get(i);
            if (direction != 0) {
                noSet.add(choose + direction);
            }
        }
        for (int order = 0; order < 2; order++) { // 0处理左右两边间隔1位[都]有占用的，1处理其余的
            for (int i = 0; i < directionList.size(); i++) {
                int direction = directionList.get(i);
                if (direction != 0) { // 已有方向，跳过
                    continue;
                }
                int x = chooseList.get(i);
                if (order == 0) {
                    if (i != 0 && i != chooseList.size() - 1
                            && chooseList.get(i - 1) == x - 2 && chooseList.get(i + 1) == x + 2) {
                        // 第一次处理，只处理中间列、且两边间隔1列都有占用的列
                    } else {
                        continue;
                    }
                }
                if (noSet.contains(x - 1)) { // 左边不能选，选右
                    direction = 1;
                } else if (noSet.contains(x + 1)) { // 右边不能选，选左
                    direction = -1;
                } else { // 随机
                    direction = random.nextInt(1000) >= 500 ? 1 : -1;
                }
                directionList.set(i, direction);
                noSet.add(x + direction);
            }
        }


        // ----- 终于可以开始放技能了 -----

        // 复制开始
        List<WasheBlock> left = new ArrayList<>();
        List<WasheBlock> right = new ArrayList<>();
        for (int i = 0; i < chooseList.size(); i++) {
            for (int y = 0; y < blockList.size(); y++) {

                WasheBlock baseBlock = blockList.get(y).get(chooseList.get(i));
                if (baseBlock.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL
                        || baseBlock.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL_BOMB) {

                    int direction = directionList.get(i);
                    int copyX = baseBlock.getX() + direction;
                    WasheBlock replacePos = blockList.get(y).get(copyX);
                    if (replacePos.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL
                            || replacePos.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL_BOMB) {

                        WasheBlock clone = baseBlock.clone();
                        clone.setEffectList(new ArrayList<>()); // 效果不能复制
                        clone.setX(copyX);
                        clone.setY(y);
                        blockList.get(y).set(copyX, clone);

                        WasheBlock tmp = baseBlock.clone();
                        tmp.setEffectList(new ArrayList<>()); // 给个假效果
                        if (direction == 1) {
                            right.add(tmp);
                        } else {
                            left.add(tmp);
                        }
                    }
                }
            }
        }

        // 添加效果
        if (right.size() > 0) {
            WasheOperateEffect effect = new WasheOperateEffect(eWasheSkillType.Card_18, 2);
            effect.setBlockList(new ArrayList<>(right));
            result.addEffect(effect);
        }
        if (left.size() > 0) {
            WasheOperateEffect effect = new WasheOperateEffect(eWasheSkillType.Card_18, 1);
            effect.setBlockList(new ArrayList<>(left));
            result.addEffect(effect);
        }
        result.addEffect(new WasheOperateEffect(eWasheSkillType.Card_18, 0));
        return new HashSet<>();
    }

    private static Set<WasheBlock> handleSkill_19(Random random, WasheGameData gameData, WasheOperateResult result) {

        List<List<WasheBlock>> blockList = gameData.getBlockList();

        // 颜色数量
        int chooseColorCount = 2;

        // 写死顺序
        // 42 43 44 45 46 47 48
        // 35 36 37 38 39 40 41
        // 28 29 30 31 32 33 34
        // 21 22 23 24 25 26 27
        // 14 15 16 17 18 19 20
        // 07 08 09 10 11 12 13
        // 00 01 02 03 04 05 06
        // 颜色1：45, 44, 46, 38, 37, 39, 31, 43, 47, 36, 30, 40, 32, 24, 17, 10, 3
        // 颜色2：21, 28, 14, 22, 29, 15, 23, 35, 7, 8, 16, 0, 42, 1, 9, 2, 3
        // 颜色3：27, 34, 20, 26, 33, 19, 25, 41, 13, 12, 18, 6, 48, 5, 11, 4, 3
        int[][] posArrs = new int[][]{
                // {45, 44, 46, 38, 37, 39, 31, 43, 47, 36, 30, 40, 32, 24, 17, 10, 3, 21, 28, 14, 22, 29, 15, 23, 35, 7, 8, 16, 0, 42, 1, 9, 2, 3, 27, 34, 20, 26, 33, 19, 25, 41, 13, 12, 18, 6, 48, 5, 11, 4, 3},
                // {27, 34, 20, 26, 33, 19, 25, 41, 13, 12, 18, 6, 48, 5, 11, 4, 3, 45, 44, 46, 38, 37, 39, 31, 43, 47, 36, 30, 40, 32, 24, 17, 10, 3, 21, 28, 14, 22, 29, 15, 23, 35, 7, 8, 16, 0, 42, 1, 9, 2, 3},
                // {21, 28, 14, 22, 29, 15, 23, 35, 7, 8, 16, 0, 42, 1, 9, 2, 3, 27, 34, 20, 26, 33, 19, 25, 41, 13, 12, 18, 6, 48, 5, 11, 4, 3, 45, 44, 46, 38, 37, 39, 31, 43, 47, 36, 30, 40, 32, 24, 17, 10, 3},
                {27, 34, 20, 26, 33, 19, 25, 41, 13, 12, 18, 6, 48, 5, 11, 4, 3, 10, 17, 24, 32, 40, 39, 47, 46, 31, 38, 45, 30, 37, 44, 36, 43, 2, 9, 1, 42, 0, 16, 8, 7, 35, 23, 15, 29, 22, 14, 28, 21},
                {21, 28, 14, 22, 29, 15, 23, 35, 7, 8, 16, 0, 42, 1, 9, 2, 30, 36, 37, 43, 44, 31, 38, 45, 32, 39, 46, 40, 47, 24, 17, 10, 3, 4, 11, 5, 48, 6, 18, 12, 13, 41, 25, 19, 33, 26, 20, 34, 27},
        };

        // 统计方块数量最多的颜色
        Map<Integer, WasheSkill19Color> colorCountMap = new HashMap<>();
        for (List<WasheBlock> list : blockList) {
            for (WasheBlock block : list) {
                colorCountMap.putIfAbsent(block.getColor(), new WasheSkill19Color(block.getColor()));
                WasheSkill19Color skill19Color = colorCountMap.get(block.getColor());
                skill19Color.setNum(skill19Color.getNum() + 1);
            }
        }
        colorCountMap.remove(eWasheColorType.None.getValue());
        List<WasheSkill19Color> list = new ArrayList<>(colorCountMap.values());
        Collections.shuffle(list, random);
        list = colorCountMap.values().stream().sorted(Comparator.comparing(WasheSkill19Color::getNum).reversed()).collect(Collectors.toList());
        // 获取颜色
        List<Integer> chooseColorList = new ArrayList<>();
        for (int i = 0; i < chooseColorCount && i < list.size(); i++) {
            chooseColorList.add(list.get(i).getColor());
        }

        // 记录移动总结果
        List<List<WasheBlock>> allMoveList = new ArrayList<>();
        List<List<WasheBlock>> allLightList = new ArrayList<>();
        for (int i = 0; i < chooseColorList.size(); i++) {
            int color = chooseColorList.get(i);

            // 找需要移动的格子，有序
            List<WasheBlock> needMoveList = new ArrayList<>();
            for (int y = blockList.size() - 1; y >= 0; y--) {
                for (int x = 0; x < blockList.get(y).size(); x++) {
                    WasheBlock block = blockList.get(y).get(x);
                    if (block.getColor() == color) {
                        if (WasheGameLogic.isBaseFourBigType(block)) {
                            needMoveList.add(block);
                        }
                    }
                }
            }
            allLightList.add(new ArrayList<>(needMoveList));

            // 被移动的格子，有序
            List<WasheBlock> beMoveList = new ArrayList<>();
            Set<Integer> posSet = new HashSet<>();
            int[] posArr = posArrs[i];
            for (int j = 0; j < needMoveList.size(); j++) {
                int pos = posArr[j];
                posSet.add(pos);
                beMoveList.add(getBlock(blockList, pos));
            }

            List<WasheBlock> moveList = new ArrayList<>();

            // 主动移动
            for (int j = 0; j < needMoveList.size(); j++) {
                WasheBlock from = needMoveList.get(j);
                WasheBlock fromClone = from.clone();
                WasheBlock to = beMoveList.get(j);

                fromClone.setX(to.getX());
                fromClone.setY(to.getY());
                blockList.get(fromClone.getY()).set(fromClone.getX(), fromClone);
                moveList.add(from);
                moveList.add(fromClone);
            }

            // 被动移动
            Collections.shuffle(needMoveList, random);
            int index = 0;
            for (WasheBlock to : beMoveList) {
                if (to.getColor() == color) {
                    continue;
                }
                while (posSet.contains(getPos(blockList, needMoveList.get(index)))) {
                    index++;
                }
                WasheBlock from = needMoveList.get(index);

                WasheBlock toClone = to.clone();
                toClone.setX(from.getX());
                toClone.setY(from.getY());
                blockList.get(toClone.getY()).set(toClone.getX(), toClone);
                moveList.add(to);
                moveList.add(toClone);
                index++;
            }

            allMoveList.add(moveList);
        }

        // 技能效果
        for (int i = 0; i < chooseColorList.size(); i++) {
            WasheOperateEffect effect1 = new WasheOperateEffect(eWasheSkillType.Card_19, 1);
            WasheOperateEffect effect2 = new WasheOperateEffect(eWasheSkillType.Card_19, 2);
            effect2.setParam(i + 2);

            List<WasheBlock> moveList = allMoveList.get(i);
            List<WasheBlock> lightList = allLightList.get(i);
            for (int j = 0; j < lightList.size(); j++) {
                effect1.addBlock(lightList.get(j));
            }
            for (int j = 0; j < moveList.size() - 1; j += 2) {
                effect2.addBlock(moveList.get(j));
                effect2.addBlock(moveList.get(j + 1));
            }
            result.addEffect(effect1);
            result.addEffect(effect2);
        }
        result.addEffect(new WasheOperateEffect(eWasheSkillType.Card_19, 0));

        return new HashSet<>();
    }

    private static Set<WasheBlock> handleSkill_20(WasheConfig config, Random random,
                                                  WasheGameData gameData, WasheOperateResult result, WasheUserGameData userGameData, int roomRound, int turnPlayer) {

        List<List<WasheBlock>> blockList = gameData.getBlockList();

        // 写死三种颜色
        int chooseColorCount = 3;

        // 随机三个颜色
        List<Integer> colorList = new ArrayList<>();
        List<Integer> chooseColorList = new ArrayList<>();
        for (eWasheColorType colorType : eWasheColorType.values()) {
            if (colorType != eWasheColorType.None && colorType != eWasheColorType.Red && colorType != eWasheColorType.Blue) {
                colorList.add(colorType.getValue());
            }
        }
        for (int i = 0; i < chooseColorCount && colorList.size() > 0; i++) {
            int color = colorList.remove(random.nextInt(colorList.size()));
            chooseColorList.add(color);
        }

        // 变色+消除
        for (int i = 0; i < chooseColorList.size() - 1; i++) {
            int baseColor = chooseColorList.get(i);
            int toColor = chooseColorList.get(i + 1);

            Set<WasheBlock> set = new HashSet<>();
            for (List<WasheBlock> list : blockList) {
                for (WasheBlock block : list) {
                    if (block.getColor() == baseColor) {
                        if (block.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL
                                || block.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL_BOMB) {
                            WasheBlock clone = block.clone();
                            clone.setColor(toColor);
                            WasheSceneLogic.scene_12_checkEffectChange(clone, gameData);
                            blockList.get(clone.getY()).set(clone.getX(), clone);
                            set.add(clone);
                        }
                    }
                }
            }

            // 技能效果
            WasheOperateEffect effect1 = new WasheOperateEffect(eWasheSkillType.Card_20, 1);
            effect1.setBlockList(new ArrayList<>(set));
            effect1.setParam(baseColor);
            result.addEffect(effect1);
            WasheOperateEffect effect2 = new WasheOperateEffect(eWasheSkillType.Card_20, 2);
            effect2.setBlockList(new ArrayList<>(set));
            effect2.setParam(toColor);
            result.addEffect(effect2);
            // 消除
            if (i < chooseColorList.size() - 1) {
                WasheGameLogic.bigEliminate(config, gameData, userGameData, null, new HashSet<>(), result, random, -1, roomRound, turnPlayer);
            }
        }
        result.addEffect(new WasheOperateEffect(eWasheSkillType.Card_20, 0));

        return new HashSet<>();
    }

    private static Set<WasheBlock> handleSkill_21(WasheConfig config, Random random,
                                                  WasheGameData gameData, WasheOperateResult result) {

        List<List<WasheBlock>> blockList = gameData.getBlockList();

        // 配置
        WasheCardConfig cardConfig = config.getCardConfigMap().get(eWasheSkillType.Card_21.getValue());
        long count = cardConfig.getSkillParamList().get(0);

        // 可选择方块
        Set<Integer> colorSet = new HashSet<>();
        List<WasheBlock> all = new ArrayList<>();
        for (int y = 1; y < blockList.size() - 1; y++) {
            for (int x = 1; x < blockList.get(y).size() - 1; x++) {
                WasheBlock block = blockList.get(y).get(x);
                if (block.getColor() != eWasheColorType.Red.getValue() && block.getColor() != eWasheColorType.Blue.getValue()) {
                    if (block.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL) {
                        all.add(block);
                        colorSet.add(block.getColor());
                    }
                }
            }
        }

        // 统计可选颜色
        ArrayList<Integer> colorList = new ArrayList<>(colorSet);

        // 随机选方块
        List<WasheBlock> paperFlowerList = new ArrayList<>();
        List<List<WasheBlock>> allBoomList = new ArrayList<>();
        for (int i = 0; i < count; i++) {

            // 本次随机可选
            List<WasheBlock> list = new ArrayList<>();
            if (colorList.size() > 0) { // 尽量不同种颜色都来一个
                int color = colorList.remove(random.nextInt(colorList.size()));
                for (WasheBlock block : all) {
                    if (block.getColor() == color) {
                        list.add(block);
                    }
                }
            }
            if (list.isEmpty()) {
                list = all;
            }
            if (list.isEmpty()) {
                break;
            }

            // 随机方块
            WasheBlock block = list.remove(random.nextInt(list.size()));
            all.remove(block);

            // 替换窗花
            block.setBlockType(eWasheBlockType.PaperFlower);
            WasheSceneLogic.scene_12_checkEffectChange(block, gameData);

            // 计算爆炸效果
            List<WasheBlock> boomList = new ArrayList<>();
            boomList.add(block);

            int x = block.getX();
            int y = block.getY();
            List<WasheBlock> existList = new ArrayList<>();
            if (WasheGameLogic.isXyExist(blockList, x, y + 1)) existList.add(blockList.get(y + 1).get(x));
            if (WasheGameLogic.isXyExist(blockList, x + 1, y)) existList.add(blockList.get(y).get(x + 1));
            if (WasheGameLogic.isXyExist(blockList, x, y - 1)) existList.add(blockList.get(y - 1).get(x));
            if (WasheGameLogic.isXyExist(blockList, x - 1, y)) existList.add(blockList.get(y).get(x - 1));
            for (WasheBlock tmpBlock : existList) {
                if (tmpBlock.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL) {
                    boomList.add(tmpBlock);
                }
                all.remove(tmpBlock);
            }

            // 添加结果
            paperFlowerList.add(block);
            allBoomList.add(boomList);
        }

        // 技能效果
        for (List<WasheBlock> list : allBoomList) {
            WasheOperateEffect effect = new WasheOperateEffect(eWasheSkillType.Card_21, 1);
            effect.setBlockList(list);
            effect.setParam(list.get(0).getColor());
            result.addEffect(effect);
        }
        result.addEffect(new WasheOperateEffect(eWasheSkillType.Card_21, 0));

        // 随机一个小窗花消除
        WasheBlock chooseBlock = null;
        if (paperFlowerList.size() > 0) {
            int randomIndex = random.nextInt(paperFlowerList.size());
            chooseBlock = paperFlowerList.get(randomIndex);
        }

        Set<WasheBlock> set = new HashSet<>();
        for (List<WasheBlock> list : allBoomList) {
            set.addAll(list.subList(1, list.size()));
        }
        set.add(chooseBlock);
        return set;
    }

    private static Set<WasheBlock> handleSkill_22(WasheConfig config, Random random,
                                                  WasheGameData gameData, WasheOperateResult result,
                                                  WasheUserGameData userGameData) {

        List<List<WasheBlock>> blockList = gameData.getBlockList();

        // 配置
        WasheCardConfig cardConfig = config.getCardConfigMap().get(eWasheSkillType.Card_22.getValue());
        // List<Long> paramList = cardConfig.getSkillParamList();
        // int turnUseTimes = userGameData.getCard().getTurnUseTimes();
        // int paramIndex = Math.min(turnUseTimes, paramList.size() - 1);
        // long count = paramList.get(paramIndex);
        long count = cardConfig.getSkillParamList().get(0);

        // 可选方块
        List<WasheBlock> all = new ArrayList<>();
        List<WasheBlock> skill22BlockList = new ArrayList<>();
        for (List<WasheBlock> list : blockList) {
            for (WasheBlock block : list) {
                if (block.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL) {
                    boolean isSkill22Block = false;
                    for (WasheBlockEffect effect : block.getEffectList()) {
                        if (effect.getEffectType() == eWasheBlockEffectType.Skill_22) {
                            isSkill22Block = true;
                            effect.setTimes(0); // 有恶魔方块要重置次数
                            break;
                        }
                    }

                    if (isSkill22Block) {
                        skill22BlockList.add(block);
                    } else {
                        all.add(block);
                    }
                }
            }
        }

        // 打乱
        Collections.shuffle(all, random);

        // 抽几个格子标记
        long createCount = count - skill22BlockList.size();
        if (createCount > 0) {
            WasheOperateEffect effect1 = new WasheOperateEffect(eWasheSkillType.Card_22, 1);
            for (int i = 0; i < createCount && i < all.size(); i++) { // 补充满

                WasheBlockEffect blockEffect = new WasheBlockEffect(eWasheBlockEffectType.Skill_22);
                blockEffect.setEffectValue(random.nextInt(3) + 1); // 1、2、3对应Y、X、十字
                WasheBlock block = all.get(i);
                block.addEffect(blockEffect);

                effect1.addBlock(block);
                skill22BlockList.add(block);
            }
            result.addEffect(effect1);
        }

        // 技能结束
        result.addEffect(new WasheOperateEffect(eWasheSkillType.Card_22, 0));
        return new HashSet<>(skill22BlockList);
    }

    /**
     * 手工少女
     * 1: 丢宝箱   宝箱位置
     * 2: 吸收    第一个格子是机巧盒  后面的是被吸收的格子
     * 3: 放出炸弹     第一个格子是机巧盒  后面的是炸弹格子
     */
    private static Set<WasheBlock> handleSkill_23(WasheConfig config, WasheGameData gameData, WasheOperateResult result, Random random) {
        // 配置
        WasheCardConfig cardConfig = config.getCardConfigMap().get(eWasheSkillType.Card_23.getValue());
        List<List<WasheBlock>> blockList = gameData.getBlockList();
        // 找机巧盒位置, 先判断有没有机巧盒
        WasheOperateEffect effect1 = new WasheOperateEffect(eWasheSkillType.Card_23, 1);
        WasheBlock smartBoxBlock = WasheGameLogic.getSmartBoxBlock(gameData);
        if (smartBoxBlock == null) {
            // 固定顺序 y:0->6  x: 3, 2, 4, 1, 5, 0, 6
            int[] xArr = new int[]{3, 2, 4, 1, 5, 0, 6};
            boolean isFind = false;
            for (int x : xArr) {
                if (isFind) {
                    break;
                }
                for (int y = 0; y < 7; y++) {
                    if (isFind) {
                        break;
                    }
                    WasheBlock block = blockList.get(y).get(x);
                    if (block == null || block.getBlockType() != eWasheBlockType.Normal) {
                        continue;
                    }
                    // 替换成机巧盒
                    block.setBlockType(eWasheBlockType.SmartBox);
                    block.setColor(eWasheColorType.None.getValue());
                    effect1.addBlock(block);
                    result.addEffect(effect1);
                    isFind = true;
                    smartBoxBlock = block;
                }
            }
        }
        // 随机吸n个颜色（先保证有）
        long colorNum = cardConfig.getSkillParamList().get(0);
        Set<Integer> colorSet = new HashSet<>();
        for (List<WasheBlock> list : blockList) {
            for (WasheBlock block : list) {
                if (block.getBlockType().getBigType() != eWasheBlockType.BIG_TYPE_NORMAL) {
                    continue;
                }
                // 过滤下
                if (block.getColor() == eWasheColorType.None.getValue() ||
                        block.getColor() == eWasheColorType.Blue.getValue() ||
                        block.getColor() == eWasheColorType.Red.getValue()) {
                    continue;
                }
                colorSet.add(block.getColor());
            }
        }
        List<Integer> colorList = new ArrayList<>(colorSet);
        List<Integer> chooseList = new ArrayList<>();
        for (int i = 0; i < colorNum; i++) {
            if (colorList.size() > 0) {
                chooseList.add(colorList.remove(random.nextInt(colorList.size())));
            } else {
                break;
            }
        }
        // 获取消除格子
        Set<WasheBlock> set = new HashSet<>();
        for (List<WasheBlock> list : blockList) {
            for (WasheBlock block : list) {
                if (chooseList.contains(block.getColor()) && block.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL) {
                    set.add(block);
                }
            }
        }
        WasheOperateEffect effect2 = new WasheOperateEffect(eWasheSkillType.Card_23, 2);
        // 第一个格子是机巧盒
        effect2.getBlockList().add(smartBoxBlock);
        effect2.getBlockList().addAll(new ArrayList<>(set));
        result.addEffect(effect2);
        return new HashSet<>(set);
    }

    /**
     * 张三丰
     * 1: 移动  [格子1，被替换的格子1，格子2，被替换的格子2 。。。。]
     * param 1: 向上 2、向下 3、向左 4、向右
     */
    private static Set<WasheBlock> handleSkill_24(WasheGameData gameData, WasheUseSkillParam param, WasheOperateResult result) {
        List<List<WasheBlock>> blockList = gameData.getBlockList();

        // 选择方块拿颜色
        if (!WasheGameLogic.isXyExist(blockList, param.getX(), param.getY())) {
            return new HashSet<>();
        }
        WasheBlock block = blockList.get(param.getY()).get(param.getX());
        int color = block.getColor();
        if (color == 0) {
            return new HashSet<>();
        }

        Set<WasheBlock> set = new HashSet<>();
        for (List<WasheBlock> list : blockList) {
            for (WasheBlock data : list) {
                if (data.getColor() == color) {
                    set.add(data.clone());
                }
            }
        }
        // 开始打太极
        // 上下左右
        int[][] dirs = new int[][]{{0, 1}, {0, -1}, {-1, 0}, {1, 0}};
        for (int i = 0; i < dirs.length; i++) {
            WasheOperateEffect effect = new WasheOperateEffect(eWasheSkillType.Card_24, 1);
            for (WasheBlock washeBlock : new ArrayList<>(set)) {
                if (WasheGameLogic.isXyExist(blockList, washeBlock.getX() + dirs[i][0], washeBlock.getY() + dirs[i][1])) {
                    WasheBlock targetBlock = blockList.get(washeBlock.getY() + dirs[i][1]).get(washeBlock.getX() + dirs[i][0]);
                    if (targetBlock.getBlockType().getBigType() != eWasheBlockType.BIG_TYPE_NORMAL && targetBlock.getBlockType().getBigType() != eWasheBlockType.BIG_TYPE_NORMAL_BOMB) {
                        continue;
                    }
                    targetBlock.setColor(color);
                    WasheBlock clone = targetBlock.clone();
                    effect.addBlock(washeBlock.clone());
                    effect.addBlock(clone);
                } else {
                    // 不存在的格子
                    effect.addBlock(washeBlock.clone());
                    // 假格子数据，客户端要表现
                    WasheBlock clone = washeBlock.clone();
                    clone.setX(washeBlock.getX() + dirs[i][0]);
                    clone.setY(washeBlock.getY() + dirs[i][1]);
                    effect.addBlock(clone);
                }
            }
            effect.setParam(i + 1);
            result.addEffect(effect);
        }
        result.addEffect(new WasheOperateEffect(eWasheSkillType.Card_24, 0));
        return new HashSet<>();
    }

    // ================================================================

    private static Set<WasheBlock> handleSkill_1001(Random random, WasheGameData gameData, WasheOperateResult result) {
        // 重排
        WasheGameLogic.rearrangeBlock(gameData, random);
        List<WasheBlock> all = new ArrayList<>();
        for (List<WasheBlock> list : gameData.getBlockList()) {
            for (WasheBlock block : list) {
                all.add(block.clone());
            }
        }

        // 添加效果
        WasheOperateEffect effect = new WasheOperateEffect(eWasheSkillType.Skill_1001, 1);
        effect.setBlockList(all);
        result.addEffect(effect);
        return new HashSet<>();
    }

    private static Set<WasheBlock> handleSkill_1002(WasheGameData gameData, WasheUseSkillParam skillParam, WasheOperateResult result) {
        Set<WasheBlock> set = new HashSet<>();
        // 选择格子
        List<List<WasheBlock>> blockList = gameData.getBlockList();
        if (WasheGameLogic.isXyExist(blockList, skillParam.getX(), skillParam.getY())) {
            set.add(blockList.get(skillParam.getY()).get(skillParam.getX()));
        }
        // 添加效果
        WasheOperateEffect effect = new WasheOperateEffect(eWasheSkillType.Skill_1002, 1);
        effect.setBlockList(new ArrayList<>(set));
        result.addEffect(effect);
        return set;
    }

    private static Set<WasheBlock> handleSkill_1003(WasheConfig config, WasheGameData gameData, WasheOperateResult result,
                                                    WasheUserGameData userGameData, WasheUseSkillParam skillParam, Random random,
                                                    int roomRound, int turnPlayer) {

        // 改成移动类型再移动
        result.setType(eWasheOperateType.Move);

        // 交换方块消除
        WasheMoveParam moveParam = new WasheMoveParam(skillParam.getX(), skillParam.getY(), skillParam.getToX(), skillParam.getToY());
        WasheGameLogic.moveBlock(config, random, gameData, result, moveParam, userGameData, -1, roomRound, turnPlayer);
        WasheSceneLogic.operateEnd(config, random, gameData, result);

        // 改回盘面技能类型
        result.setType(eWasheOperateType.UseSkill);

        return new HashSet<>();
    }

    private static Set<WasheBlock> handleSkill_1004(WasheConfig config, Random random, WasheGameData gameData, WasheOperateResult result) {
        WasheSkillConfig skillConfig = config.getSkillConfigMap().get(eWasheSkillType.Skill_1004.getValue());
        long colorNum = skillConfig.getSkillParamList().get(0);

        // 随机2色
        List<Integer> colorList = new ArrayList<>();
        for (eWasheColorType type : eWasheColorType.values()) {
            if (type.getValue() > 2) {
                colorList.add(type.getValue());
            }
        }
        List<Integer> chooseList = new ArrayList<>();
        for (int i = 0; i < colorNum; i++) {
            if (colorList.size() > 0) {
                chooseList.add(colorList.remove(random.nextInt(colorList.size())));
            } else {
                break;
            }
        }

        Set<WasheBlock> set = new HashSet<>();
        int index = 0;
        List<List<WasheBlock>> blockList = gameData.getBlockList();
        for (List<WasheBlock> list : blockList) {
            for (WasheBlock block : list) {
                index++;
                if (block.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL
                        || block.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL_BOMB) {
                    block.setColor(chooseList.get(index % chooseList.size()));
                    WasheSceneLogic.scene_12_checkEffectChange(block, gameData);
                    set.add(block);
                }
            }
        }

        // 添加效果
        WasheOperateEffect operateEffect = new WasheOperateEffect(eWasheSkillType.Skill_1004, 1);
        operateEffect.setBlockList(new ArrayList<>(set));
        result.addEffect(operateEffect);

        return new HashSet<>();
    }

    private static Set<WasheBlock> handleSkill_1005(WasheConfig config, Random random, WasheGameData gameData, WasheOperateResult result) {
        WasheSkillConfig skillConfig = config.getSkillConfigMap().get(eWasheSkillType.Skill_1005.getValue());
        long num = skillConfig.getSkillParamList().get(0);

        // 获取可选方块
        List<WasheBlock> canRandomList = new ArrayList<>();
        List<List<WasheBlock>> blockList = gameData.getBlockList();
        for (List<WasheBlock> list : blockList) {
            for (WasheBlock block : list) {
                if (block.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL) {
                    canRandomList.add(block);
                }
            }
        }

        // 打乱
        Collections.shuffle(canRandomList, random);

        // 取方块变流星
        List<WasheBlock> chooseList = new ArrayList<>();
        for (int i = 0; i < num && i < canRandomList.size(); i++) {
            WasheBlock block = canRandomList.get(i);
            block.setBlockType(eWasheBlockType.LiuXing_SkillCreate);
            chooseList.add(block);
        }

        // 添加效果
        if (chooseList.size() > 0) {
            WasheOperateEffect effect = new WasheOperateEffect(eWasheSkillType.Skill_1005, 1);
            effect.setBlockList(chooseList);
            result.addEffect(effect);
        }

        return new HashSet<>();
    }

    private static Set<WasheBlock> handleSkill_1006(WasheConfig config, WasheGameData gameData, WasheOperateResult result, WasheUseSkillParam skillParam) {

        Set<WasheBlock> set = new HashSet<>();
        List<List<WasheBlock>> blockList = gameData.getBlockList();
        // 横
        if (skillParam.getY() < blockList.size()) {
            set.addAll(blockList.get(skillParam.getY()));
        }
        // 竖
        if (skillParam.getX() < blockList.get(0).size()) {
            for (List<WasheBlock> list : blockList) {
                set.add(list.get(skillParam.getX()));
            }
        }

        // 加效果
        if (set.size() > 0) {
            WasheOperateEffect effect = new WasheOperateEffect(eWasheSkillType.Skill_1006, 1);
            effect.setBlockList(new ArrayList<>(set));
            result.addEffect(effect);
        }

        return set;
    }

    private static Set<WasheBlock> handleSkill_1007(WasheConfig config, Random random, WasheGameData gameData, WasheOperateResult result, WasheUseSkillParam skillParam) {

        List<List<WasheBlock>> blockList = gameData.getBlockList();

        // 选择的列
        int chooseX = skillParam.getX();
        if (chooseX < 0 || chooseX >= blockList.get(0).size()) {
            return new HashSet<>();
        }

        // 方向
        int direction;
        if (chooseX == 0) {
            direction = 1;
        } else if (chooseX == blockList.get(0).size() - 1) {
            direction = -1;
        } else {
            direction = random.nextInt(1000) < 500 ? -1 : 1;
        }

        // 复制开始
        Set<WasheBlock> set = new HashSet<>();
        for (List<WasheBlock> list : blockList) {
            WasheBlock fromBlock = list.get(chooseX);
            int toX = chooseX + direction;
            WasheBlock toBlock = list.get(toX);

            if (fromBlock.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL || fromBlock.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL_BOMB) {
                if (toBlock.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL || toBlock.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL_BOMB) {

                    WasheBlock clone = fromBlock.clone();
                    clone.setEffectList(new ArrayList<>()); // 效果不能复制
                    clone.setX(toX);
                    blockList.get(clone.getY()).set(clone.getX(), clone);

                    WasheBlock tmp = fromBlock.clone();
                    tmp.setEffectList(new ArrayList<>()); // 给个假效果
                    set.add(tmp);
                }
            }
        }

        // 添加效果
        if (set.size() > 0) {
            int effectNo = direction == 1 ? 2 : 1;
            WasheOperateEffect effect = new WasheOperateEffect(eWasheSkillType.Skill_1007, effectNo);
            effect.setBlockList(new ArrayList<>(set));
            result.addEffect(effect);
        }
        return new HashSet<>();
    }

    private static Set<WasheBlock> handleSkill_1008(WasheConfig config, Random random, WasheGameData gameData, WasheOperateResult result) {

        List<List<WasheBlock>> blockList = gameData.getBlockList();

        // 找可以随机的方块
        Set<Integer> colorSet = new HashSet<>();
        for (List<WasheBlock> list : blockList) {
            for (WasheBlock block : list) {
                if (block.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL
                        || block.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL_BOMB
                        || block.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_SPECIAL) {
                    colorSet.add(block.getColor());
                }
            }
        }
        colorSet.remove(0);
        if (colorSet.size() == 0) {
            return new HashSet<>();
        }

        // 随机一个出来
        List<Integer> colorList = new ArrayList<>(colorSet);
        int index = random.nextInt(colorList.size());
        int color = colorList.get(index);

        // 红釉青花特殊处理
        WasheSceneLogic.scene_08_changeColor(gameData, color);

        // 消除同色
        Set<WasheBlock> all = new HashSet<>();
        for (List<WasheBlock> list : blockList) {
            for (WasheBlock tmpBlock : list) {
                if (tmpBlock.getColor() == color) {
                    if (tmpBlock.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL
                            || tmpBlock.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL_BOMB
                            || tmpBlock.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_SPECIAL) {
                        all.add(tmpBlock);
                    }
                }
            }
        }

        // 技能效果
        WasheOperateEffect effect = new WasheOperateEffect(eWasheSkillType.Skill_1008, 1);
        effect.setBlockList(new ArrayList<>(all));
        result.addEffect(effect);

        return all;
    }

    private static Set<WasheBlock> handleSkill_1009(WasheConfig config, Random random, WasheGameData gameData, WasheOperateResult result) {

        // 参数
        WasheSkillConfig skillConfig = config.getSkillConfigMap().get(eWasheSkillType.Skill_1009.getValue());
        long canMoveTimes = skillConfig.getSkillParamList().get(0);

        List<List<WasheBlock>> blockList = gameData.getBlockList();

        Set<WasheBlock> movedSet = new HashSet<>();

        int moveTimes = 0;
        for (int times = 0; times < 10; times++) { // 最多检查10轮，如果本轮没有可移动的，下面会break
            int curSize = movedSet.size();

            if (moveTimes >= canMoveTimes) break;
            for (int y = 0; y < blockList.size(); y++) {
                if (moveTimes >= canMoveTimes) break;
                for (int x = 0; x < blockList.get(y).size(); x++) {
                    if (moveTimes >= canMoveTimes) break;

                    WasheBlock block1 = blockList.get(y).get(x);
                    if (movedSet.contains(block1)) {
                        continue;
                    }

                    // 跟右边交换
                    int x2 = x + 1;
                    int y2 = y;
                    if (WasheGameLogic.isXyExist(blockList, x2, y2) && !movedSet.contains(blockList.get(y2).get(x2))) {
                        WasheBlock block2 = blockList.get(y2).get(x2);
                        WasheGameLogic.exchangeBlock(blockList, x, y, x2, y2, null);
                        List<WasheBlock> list1 = getSameColorList(blockList, block1);
                        List<WasheBlock> list2 = getSameColorList(blockList, block2);
                        if (list1 != null || list2 != null) {

                            Set<WasheBlock> set = new HashSet<>();
                            if (list1 != null) set.addAll(list1);
                            if (list2 != null) set.addAll(list2);

                            movedSet.addAll(set);
                            movedSet.add(block1);
                            movedSet.add(block2);

                            WasheOperateEffect effect1 = new WasheOperateEffect(eWasheSkillType.Skill_1009, 1);
                            effect1.addBlock(block1);
                            effect1.addBlock(block2);
                            result.addEffect(effect1);

                            WasheOperateEffect effect2 = new WasheOperateEffect(eWasheEffectType.HighLight);
                            effect2.setBlockList(new ArrayList<>(set));
                            result.addEffect(effect2);
                            moveTimes++;
                            continue;
                        } else {
                            WasheGameLogic.exchangeBlock(blockList, x, y, x2, y2, null);
                        }
                    }

                    // 跟上边交换
                    x2 = x;
                    y2 = y + 1;
                    if (WasheGameLogic.isXyExist(blockList, x2, y2) && !movedSet.contains(blockList.get(y2).get(x2))) {
                        WasheBlock block2 = blockList.get(y2).get(x2);
                        WasheGameLogic.exchangeBlock(blockList, x, y, x2, y2, null);
                        List<WasheBlock> list1 = getSameColorList(blockList, block1);
                        List<WasheBlock> list2 = getSameColorList(blockList, block2);
                        if (list1 != null || list2 != null) {

                            Set<WasheBlock> set = new HashSet<>();
                            if (list1 != null) set.addAll(list1);
                            if (list2 != null) set.addAll(list2);

                            movedSet.addAll(set);
                            movedSet.add(block1);
                            movedSet.add(block2);

                            WasheOperateEffect effect1 = new WasheOperateEffect(eWasheSkillType.Skill_1009, 1);
                            effect1.addBlock(block1);
                            effect1.addBlock(block2);
                            result.addEffect(effect1);

                            WasheOperateEffect effect2 = new WasheOperateEffect(eWasheEffectType.HighLight);
                            effect2.setBlockList(new ArrayList<>(set));
                            result.addEffect(effect2);
                            moveTimes++;
                            continue;
                        } else {
                            WasheGameLogic.exchangeBlock(blockList, x, y, x2, y2, null);
                        }
                    }

                }
            }

            if (curSize == movedSet.size()) {
                break;
            }
        }

        return new HashSet<>();
    }

    private static Set<WasheBlock> handleSkill_1010(WasheConfig config, WasheGameData gameData, WasheOperateResult result, WasheUseSkillParam skillParam) {

        List<List<WasheBlock>> blockList = gameData.getBlockList();
        List<WasheBlock> list = blockList.get(blockList.size() / 2);
        WasheBlock block = list.get(list.size() / 2);
        int baseX = block.getX();
        int baseY = block.getY();

        // 该位置如果是百宝箱，则选择该位置附近的格子
        int[][] xy = new int[][]{
                {0, -1}, // 下
                {-1, -1}, // 左下
                {-1, 0}, // 左
                {-1, 1}, // 左上
                {0, 1}, // 上
                {1, 1}, // 右上
                {1, 0}, // 右
                {1, -1}, // 右下
        };
        int index = 0;
        while (block.getBlockType() == eWasheBlockType.BaiBaoXiang && index < xy.length) {
            block = blockList.get(baseY + xy[index][1]).get(baseX + xy[index][0]);
            index++;
        }
        if (index >= xy.length) {
            return new HashSet<>();
        }

        // 红釉青花特殊处理
        int blue = skillParam.getSide() == 1 ? eWasheColorType.Red.getValue() : eWasheColorType.Blue.getValue();
        WasheSceneLogic.scene_08_changeColor(gameData, blue);

        // 修改
        block.setBlockType(eWasheBlockType.DiLei);

        // 加效果
        WasheOperateEffect effect = new WasheOperateEffect(eWasheSkillType.Skill_1010, 1);
        effect.setBlockList(Collections.singletonList(block));
        result.addEffect(effect);

        return Collections.singleton(block);
    }

    private static Set<WasheBlock> handleSkill_1011(WasheConfig config, WasheGameData gameData, WasheOperateResult result, WasheUseSkillParam skillParam) {
        List<List<WasheBlock>> blockList = gameData.getBlockList();

        WasheBlock from = blockList.get(skillParam.getY()).get(skillParam.getX()).clone();
        from.setX(skillParam.getToX());
        from.setY(skillParam.getToY());
        WasheBlock to = blockList.get(skillParam.getToY()).get(skillParam.getToX()).clone();
        to.setX(skillParam.getX());
        to.setY(skillParam.getY());
        // 替换
        blockList.get(from.getY()).set(from.getX(), from);
        blockList.get(to.getY()).set(to.getX(), to);

        List<WasheBlock> list = new ArrayList<>();
        list.add(from);
        list.add(to);

        WasheOperateEffect effect = new WasheOperateEffect(eWasheSkillType.Skill_1011, 1);
        effect.setBlockList(list);
        result.addEffect(effect);

        return new HashSet<>();
    }

    private static Set<WasheBlock> handleSkill_1012(WasheConfig config, Random random, WasheGameData gameData, WasheOperateResult result, WasheUseSkillParam param) {

        // 参数
        WasheSkillConfig skillConfig = config.getSkillConfigMap().get(eWasheSkillType.Skill_1012.getValue());
        long num = skillConfig.getSkillParamList().get(0);

        int blue = param.getSide() == 1 ? eWasheColorType.Red.getValue() : eWasheColorType.Blue.getValue();
        List<List<WasheBlock>> blockList = gameData.getBlockList();

        // 拿可选方块
        List<WasheBlock> canRandomList = new ArrayList<>();
        for (List<WasheBlock> list : blockList) {
            for (WasheBlock block : list) {
                if (block.getColor() != blue && block.getBlockType() == eWasheBlockType.Normal) {
                    canRandomList.add(block);
                }
            }
        }
        // 打乱
        Collections.shuffle(canRandomList, random);

        // 取方块变色
        List<WasheBlock> list = new ArrayList<>();
        for (int i = 0; i < num && i < canRandomList.size(); i++) {
            WasheBlock block = canRandomList.get(i);
            block.setColor(blue);
            WasheSceneLogic.scene_12_checkEffectChange(block, gameData);
            list.add(block);
        }

        // 加效果
        WasheOperateEffect effect = new WasheOperateEffect(eWasheSkillType.Skill_1012, 1);
        effect.setBlockList(list);
        result.addEffect(effect);

        return new HashSet<>();
    }

    private static Set<WasheBlock> handleSkill_1013(WasheConfig config, WasheGameData gameData, WasheOperateResult result, WasheUseSkillParam param) {

        List<List<WasheBlock>> blockList = gameData.getBlockList();

        // 拿可选方块
        List<WasheBlock> chooseList = new ArrayList<>();
        for (List<WasheBlock> list : blockList) {
            for (WasheBlock block : list) {
                if (block.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL_BOMB ||
                        block.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_SPECIAL_BOMB) {
                    chooseList.add(block);
                }
            }
        }

        // 加效果
        WasheOperateEffect effect = new WasheOperateEffect(eWasheSkillType.Skill_1013, 1);
        effect.setBlockList(chooseList);
        result.addEffect(effect);

        return new HashSet<>(chooseList);
    }


    // =========================================

    private static void moveChess(Random random, List<List<WasheBlock>> blockList, Set<WasheBlock> allMoveSet,
                                  List<WasheBlock> needMoveList, int[][] movePosArr, List<WasheBlock> curMoveList,
                                  List<WasheBlock> nextNeedMoveList, Set<WasheBlock> roundMoveSet) {
        for (WasheBlock block : needMoveList) {

            // 先按顺序移动
            boolean success = false;
            List<WasheBlock> exist = new ArrayList<>();
            for (int[] movePos : movePosArr) {
                int tmpX = block.getX() + movePos[0];
                int tmpY = block.getY() + movePos[1];
                if (WasheGameLogic.isXyExist(blockList, tmpX, tmpY)) {
                    WasheBlock tmpBlock = blockList.get(tmpY).get(tmpX);
                    exist.add(tmpBlock);
                    if (!allMoveSet.contains(tmpBlock)) { // 方块存在 && 未移动过 => 直接移动
                        if (WasheGameLogic.isBaseFourBigType(block)) {
                            allMoveSet.add(tmpBlock);
                            roundMoveSet.add(tmpBlock);
                            nextNeedMoveList.add(tmpBlock);
                            curMoveList.add(block);
                            curMoveList.add(tmpBlock);
                            success = true;
                            break;
                        }
                    }
                }
            }
            if (success) {
                continue;
            }

            // 移动失败，则优先非本轮移动的位置
            ArrayList<WasheBlock> list = new ArrayList<>(exist);
            list.removeAll(roundMoveSet);
            // 本轮位置为空，最后才是所有位置随机
            if (list.isEmpty()) {
                list = new ArrayList<>(exist);
            }

            if (!list.isEmpty()) {
                WasheBlock tmpBlock = list.remove(random.nextInt(list.size()));
                allMoveSet.add(tmpBlock);
                roundMoveSet.add(tmpBlock);
                nextNeedMoveList.add(tmpBlock);
                curMoveList.add(block);
                curMoveList.add(tmpBlock);
            }
        }
    }

    private static int getPos(List<List<WasheBlock>> blockList, WasheBlock block) {
        return block.getY() * blockList.get(0).size()
                + block.getX();
    }

    private static WasheBlock getBlock(List<List<WasheBlock>> blockList, int pos) {
        int size = blockList.get(0).size();
        int y = pos / size;
        int x = pos % size;
        return blockList.get(y).get(x);
    }

    private static List<WasheBlock> getSameColorList(List<List<WasheBlock>> blockList, WasheBlock block) {
        List<WasheBlock> lightListHeng = new ArrayList<>();
        lightListHeng.add(block);
        List<WasheBlock> lightListShu = new ArrayList<>();
        lightListShu.add(block);

        // 上
        for (int y = block.getY() + 1; y < blockList.size(); y++) {
            if (WasheGameLogic.isXyExist(blockList, block.getX(), y) && blockList.get(y).get(block.getX()).getColor() == block.getColor()) {
                lightListShu.add(blockList.get(y).get(block.getX()));
            } else break;
        }
        // 下
        for (int y = block.getY() - 1; y >= 0; y--) {
            if (WasheGameLogic.isXyExist(blockList, block.getX(), y) && blockList.get(y).get(block.getX()).getColor() == block.getColor()) {
                lightListShu.add(blockList.get(y).get(block.getX()));
            } else break;
        }
        // 左
        for (int x = block.getX() - 1; x >= 0; x--) {
            if (WasheGameLogic.isXyExist(blockList, x, block.getY()) && blockList.get(block.getY()).get(x).getColor() == block.getColor()) {
                lightListHeng.add(blockList.get(block.getY()).get(x));
            } else break;
        }
        // 右
        for (int x = block.getX() + 1; x < blockList.get(block.getY()).size(); x++) {
            if (WasheGameLogic.isXyExist(blockList, x, block.getY()) && blockList.get(block.getY()).get(x).getColor() == block.getColor()) {
                lightListHeng.add(blockList.get(block.getY()).get(x));
            } else break;
        }

        if (lightListHeng.size() >= 3 && lightListShu.size() >= 3) {
            lightListShu.remove(0);
            lightListHeng.addAll(lightListShu);
            return lightListHeng;
        } else if (lightListHeng.size() >= 3) {
            return lightListHeng;
        } else if (lightListShu.size() >= 3) {
            return lightListShu;
        } else {
            return null;
        }
    }


}
